/*
 * Copyright (c) 2010-2011, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "alkes/opengl/internal.h"

#if defined(ALKES_WGL)

#include "alkes/opengl/WGLGraphics.h"
#include "alkes/opengl/GLImageBufferFactory.h"
#include "alkes/win32image.h"

#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "alkes-win32image.lib")

AL_OGL_EXPORT_API alkes::IGraphics* alkes_create_graphics(void* window)
{
    return alkes::WGLGraphics::create((HWND)window);
}

namespace alkes {

WGLGraphics* WGLGraphics::create(HWND hwnd, TargetBehavior behavior)
{
    switch (behavior)
    {
    case AL_BEHAVIOR_DISCARD:
    case AL_BEHAVIOR_SINGLE:
    case AL_BEHAVIOR_DOUBLE:
        break;
    default:
        return 0;
        break;
    }

    HDC hdc = GetDC(hwnd);
    if (NULL == hdc)
    {
        return NULL;
    }

    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(pfd));
    pfd.nSize       = sizeof(pfd);
    pfd.nVersion    = 1;
    pfd.dwFlags     = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|(behavior == AL_BEHAVIOR_DOUBLE ? PFD_DOUBLEBUFFER : 0);
    pfd.iPixelType  = PFD_TYPE_RGBA;
    pfd.cColorBits  = 24;
    pfd.cDepthBits  = 32;
    pfd.iLayerType  = PFD_MAIN_PLANE;

    int pixel_format;
    HGLRC hgrc;
    if (   0 == (pixel_format = ChoosePixelFormat(hdc, &pfd))
        || FALSE == SetPixelFormat(hdc, pixel_format, &pfd)
        || NULL == (hgrc = wglCreateContext(hdc)))
    {
        ReleaseDC(hwnd, hdc);
        return NULL;
    }

    wglMakeCurrent(hdc, hgrc);

    RECT rect;
    GetClientRect(hwnd, &rect);

    return new WGLGraphics(hwnd, hdc, hgrc, rect.right, rect.bottom, behavior);
}

void WGLGraphics::destroy()
{
    delete this;
}

WGLGraphics::WGLGraphics(HWND hwnd, HDC hdc, HGLRC hgrc, LONG width, LONG height, TargetBehavior behavior)
: GLGraphics((uint16_t)width, (uint16_t)height, behavior)
, hwnd_(hwnd)
, hdc_(hdc)
, hgrc_(hgrc)
{
}

WGLGraphics::~WGLGraphics()
{
    wglMakeCurrent(hdc_, 0);
    wglDeleteContext(hgrc_);
}

void WGLGraphics::flip()
{
    AL_OGL_INVOKE(glFinish());
    SwapBuffers(hdc_);

    if (hwnd_)
        ValidateRect(hwnd_ , NULL);
}

DecoderFactory* WGLGraphics::createDecoderFactory()
{
    return Win32DecoderFactory::create(createImageBufferFactory());
}

}

#endif
